Skip to content

[GSoC] LateNightQML: Effects Rack - #16884

Open
xARSENICx wants to merge 7 commits into
mixxxdj:mainfrom
xARSENICx:LateNightQML/effects
Open

[GSoC] LateNightQML: Effects Rack#16884
xARSENICx wants to merge 7 commits into
mixxxdj:mainfrom
xARSENICx:LateNightQML/effects

Conversation

@xARSENICx

@xARSENICx xARSENICx commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

This PR continues the LateNightQML skin work, focusing on bringing the effects rack to feature and visual parity with the legacy LateNight skin for both Classic and PaleMoon color schemes.

Testing the Experimental Skin

Since this is an early experimental milestone, you must first run Mixxx with the developer flag:

./build/mixxx --developer

Once Mixxx is open, switch to the experimental skin:

Preferences -> Interface -> LateNight QML (Experimental)

You can dynamically toggle between the Classic and PaleMoon color schemes under preferences.

Previews

Classic

image

PaleMoon

image

Scope of Changes

Implemented in this PR:

  • Adds the LateNightQML effects rack between the deck and mixer area and the library.
  • Supports two or four effect units through the existing LateNight toolbar settings.
  • Implements the legacy collapsed three-slot effect-chain layout with effect selectors, flow indicators, Mix controls, preset settings, mix mode, PFL, unit headers, and expansion controls.
  • Implements the expanded three-row parameter layout with effect-specific button and knob parameters, separators, focus highlighting, parameter linking, and inversion controls.
  • Adds effect-chain preset selection, saving, updating, renaming, per-slot effect selection, parameter visibility, and default-snapshot actions.
  • Implements persisted rack visibility and Super Knob settings, including the optional per-unit Super controls.
  • Adds deck, main-output, and headphone effect routing with the legacy two-deck and four-deck assignment layouts.
  • Supports controller-input highlighting and the legacy mouse focus behavior.
  • Integrates the effects rack with the existing LateNightQML mixer and responsive deck/library layout.

Dependencies

Depends on #16883 and #16858.

Tracking

GSoC: LateNightQML PR-9


readonly property bool active: control.value > 0
property url activeBackgroundSource: backgroundSource
property color activeColor: "#888888"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please define colors in res/skins/LateNightQML/LateNightTheme/LateNightTheme.qml

displayArcStart: LateNightControls.Knob.ArcStart.Minimum
group: root.group
height: 26
indicatorColor: LateNightTheme.isClassic ? "white" : "grey"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please define colors in res/skins/LateNightQML/LateNightTheme/LateNightTheme.qml

y: 38

Rectangle {
color: inverseControl.item && inverseControl.item.value > 0 ? "#9c0900" : (LateNightTheme.isClassic ? "#4b4b4b" : "#333333")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please define colors in res/skins/LateNightQML/LateNightTheme/LateNightTheme.qml

Comment on lines +27 to +33
let buttonCount = 0;
for (let index = 0; index < buttonRepeater.count; ++index) {
const loader = buttonRepeater.itemAt(index);
if (loader && loader.active) {
++buttonCount;
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make clear what is count:

Suggested change
let buttonCount = 0;
for (let index = 0; index < buttonRepeater.count; ++index) {
const loader = buttonRepeater.itemAt(index);
if (loader && loader.active) {
++buttonCount;
}
}
let activeButtonCount = 0;
for (let btnIdx = 0; btnIdx < buttonRepeater.count; ++btnIdx ) {
const loader = buttonRepeater.itemAt(btnIdx);
if (loader && loader.active) {
++activeButtonCount ;
}
}

anchors.left: parent.left
anchors.right: slotControls.left
anchors.top: parent.top
border.color: showFocus.value > 0 && Math.round(focusedEffect.value) === root.effectNumber ? LateNightTheme.effectsFocusBorderColor : (LateNightTheme.isClassic ? LateNightTheme.deckPanelBorderDark : "transparent")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit complicated. Can you please make it easier readable.

Comment on lines +120 to +124
MouseArea {
anchors.fill: parent

onClicked: root.popup.open()
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
MouseArea {
anchors.fill: parent
onClicked: root.popup.open()
}

Please double-check if this is really needed. In general we should use mouse specific behavior only where we don not want allow touch gestures.

fillMode: Image.Stretch
source: root.active ? root.activeSource : root.normalSource
}
MouseArea {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check if https://doc.qt.io/qt-6/qml-qtquick-taphandler.html would be better suited here. While LateNight is a mouse centric skin, we should block touch gestures uneccessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants